from django.core.files.storage import Storage
from fdfs_client.client import Fdfs_client
from django.conf import settings

class FastDFSStorage(Storage):
    """自定义Django的存储系统类"""
    def __init__(self, client_conf=None, server_ip=None):
        """初始化，设置参数
            如果用户自己设置client。conf就用设定的
            如果没有重新设置，就使用settings中的，其实就是使用settings中的设置
            通过更改settings中的设置来更改配置文件
        """
        if client_conf is None:
            client_conf = settings.CLIENT_CONF
        self.client_conf = client_conf
        # 设定服务器
        if server_ip is None:
            server_ip = settings.SERVER_IP
        self.server_ip = server_ip


    def _open(self, name, mode='rb'):
        """读取文件时使用"""
        pass

    def _save(self, name, content):
        """存储文件时使用，参数2是上传来的文件名，参数3是上传来的File对象"""

        # 创建fdfs客户端client,需要指定配置文件
        client = Fdfs_client(self.client_conf)

        # client 获取文件的内容
        # 也可以通过名字的方式获取
        file_data = content.read()

        # django借助client向FastDFS服务器上传文件
        # 涉及文件操作，都应该有失败机制，用try
        try:
            result = client.upload_by_buffer(file_data)
        except Exception:
        # 直接抛出错误即可
            raise

        # 根据返回数据， 判断是否上传成功
        # 看源码可以看到返回的值
        if result.get('Status') == 'Upload successed.':
            # 读取file_id
            file_id = result.get('Remote file_id')
            # 返回给Django存储起来
            # 在后台管理中，django会根据当前的界面确定所添加的图片属于哪一个模型类
            # 自动存入所对应的数据表
            return file_id
        else:
            raise Exception('上传文件到FastDFS失败')

    def exists(self, name):
        """django用来判断文件是不是存在，必须有"""

        # 由于django不存储图片，所以永远返回False， 直接保存到FastDfS中
        return False

    def url(self, name):
        """用于返回图片在服务器上完成的地址server_ip+path"""
        # 这个name就是配置fastDFS服务器时的返回的长串名字
        return self.server_ip+name
